package com.ry.aop.myaop;

import com.ry.aop.myaop.advicechain.*;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * cglib 代理工厂
 */
public class ProxyFactory2 implements MethodInterceptor {

    private Object target;

    // TODO ioc时期 扫码注解将通知类注入进来
    // 这里简单，就是定死
    private List<BaseAdvice> adviceList = new ArrayList<>();

    public ProxyFactory2() {

        // 1 2 3 4
        // 返回 4 3 2 1
        adviceList.add(new ThrowAdvice());
        adviceList.add(new ReturnAdvice());
        adviceList.add(new AfterAdvice());
        adviceList.add(new BeforeAdvice());
    }

    public UserService getProxy(Object target){

        this.target = target;

        // CGLIB  生成代理对象
        Enhancer enhancer = new Enhancer();

        // 设置父类class
        enhancer.setSuperclass(target.getClass());

        // 设置回调
        enhancer.setCallback(this);

        // 设置类加载器
        enhancer.setClassLoader(target.getClass().getClassLoader());

        return (UserService)enhancer.create();
    }

    // 这样不好，就算我只配置了一个前置通知，但是所有代码都写在了一起
    // 有没有办法提高灵活性、解耦合、该怎么办？
    // 责任链、调用链
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

        // List增强通知
        Chain chain = new Chain(adviceList,method,objects,target);

        // 调用增强链
        return chain.proceed();
    }
}
